﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Threading;
using envir2plotwatt.GUI.Configuration;
using EnergyAggregator;
using EnergyMonitor;

namespace envir2plotwatt.GUI
{
    public delegate List<string> GetMeterListDelegate();
    public delegate List<string> GetMonitorListDelegate();
    public delegate void AddMonitorMeterMappingDelegate(MonitorToMeter mapping);
    public delegate List<MonitorToMeter> GetMonitorMeterMappingDelegate();
    public delegate void DeleteMonitorMeterMappingDelegate(MonitorToMeter mapping);

    /// <summary>
    /// 
    /// </summary>
    public partial class Main : Form
    {
        private TheDoc m_doc;
        private string m_selectedMeter = "";
        private List<MeterReading> m_meterReadings = new List<MeterReading>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="doc"></param>
        public Main(TheDoc doc)
        {
            m_doc = doc;

            InitializeComponent();

            PopulateMeterList();

            tsAutoSave.Checked = m_doc.AppConfig.AutoSaveOnExit;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        public void DisplayReceivedData(string data)
        {
            if (output.InvokeRequired)
            {
                MethodInvoker del = delegate { DisplayReceivedData(data); };
                output.Invoke(del);
            }
            else
            {
                output.Text += data + Environment.NewLine;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void PopulateMeterList()
        {
            string[] meterList;

            meterList = m_doc.Aggregator.ListMeters();
            lbMeters.Items.Clear();

            lbMeters.Items.AddRange(meterList);
            m_selectedMeter = "";
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddMeter_Click(object sender, EventArgs e)
        {
            m_doc.Aggregator.AddMeter();

            // now get updated list of meters
            PopulateMeterList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDeleteMeter_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(m_selectedMeter))
            {
                m_doc.Aggregator.DeleteMeter(m_selectedMeter);
                
                // now get updated list of meters
                PopulateMeterList();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lbMeters_SelectedIndexChanged(object sender, EventArgs e)
        {
            m_selectedMeter = lbMeters.SelectedItem.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void msMonitorMapping_Click(object sender, EventArgs e)
        {
            MonitorMapping mm = new MonitorMapping();

            // TODO we should create these in the main form and then we can pass then down to other objects, or the doc should provide an interface that can be used?
            mm.GetMeterList = () => { return m_doc.Aggregator.GetMeterList(); };
            mm.GetMonitorList = () => { return m_doc.Monitor.GetMonitorList(); };
            mm.AddMonitorMapping = (mapping) => { m_doc.AppConfig.Mappings.Add(mapping); };
            mm.DelMonitorMapping = (mapping) => { m_doc.AppConfig.Mappings.Remove(mapping); };
            mm.GetMonitorMapping = () => { return m_doc.AppConfig.Mappings; };

            mm.ShowDialog();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialPortToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ChangePort cp = new ChangePort(m_doc.AppConfig.ComPort);

            if (cp.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                m_doc.AppConfig.ComPort = cp.Port;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsSaveConfiguration_Click(object sender, EventArgs e)
        {
            m_doc.SaveConfiguration();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsAutoSave_Click(object sender, EventArgs e)
        {
            tsAutoSave.Checked = !tsAutoSave.Checked;
            m_doc.AppConfig.AutoSaveOnExit = tsAutoSave.Checked;
        }

        /// <summary>
        /// Check if auto save option is set, if it is then we need to save the configuration
        /// </summary>
        /// <returns></returns>
        private bool CheckSave()
        {
            if (m_doc.AppConfig.AutoSaveOnExit)
            {
                // TODO we should return statys from save method and give options on save failure
                m_doc.SaveConfiguration();
            }

            return true;
        }

        /// <summary>
        /// Handle the plotwatt interface configuration
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsPlottWatt_Click(object sender, EventArgs e)
        {
            PlotWattConfiguration pwc = new PlotWattConfiguration();

            pwc.UserName = m_doc.AppConfig.UserName;
            pwc.Password = m_doc.AppConfig.Password;
            pwc.EnableUpload = m_doc.AppConfig.PostEnable;

            if (pwc.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                m_doc.AppConfig.UserName = pwc.UserName;
                m_doc.AppConfig.Password = pwc.Password;
                m_doc.AppConfig.PostEnable = pwc.EnableUpload;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            CheckSave();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}
